﻿local L = AceLibrary("AceLocale-2.2"):new("Nier")

local actualGears = {}
local equippedGears = {}
local pendingEquipments = {}
local prevMountType = nil

local trinketSlot = 13

local gears = {
	normal = {
		spurs = { -- Mithril Spurs
			pattern = "item:%d+:464:",
			slot = 8,
		},
		speed = { -- Minor Mount Speed Increase
			pattern = "item:%d+:930:",
			slot = 10,
		},
		carrot = { -- Carrot on a stick
			pattern = "item:11122:",
			slot = trinketSlot,
		},
		crop = { -- Riding Crop
			pattern = "item:25653:",
			slot = trinketSlot,
		},
	},

	druid = {
		charm = { -- Charm of Swift Flight
			pattern = "item:32481:",
			slot = trinketSlot,
		},
	},
}

-- Mounting types
local MT_UNMOUNT    = 0
local MT_VECHILE    = 1
local MT_AIRCRAFT   = 2
local MT_FLIGHTFORM = 3
local mountType

-- Buff patterns
local PATTERN_VECHILE         = L["^Increases speed by %d+%%$"]
local PATTERN_AIRCRAFT        = L["^Movement speed increased by %d+%% and allows you to fly$"]
NierEquip = Nier:NewModule("NierEquip")

NierEquip.options = {
	["DelayEquip"] = {
		type = "toggle",
		name = L["Delay equipping"],
		desc = L["Delay equipping when player cast spell"],
		get = function() return NierEquip.db.profile.delayEquipping end,
		set = function(v) NierEquip.db.profile.delayEquipping = v end,
	},
}

NierEquip.defaultDB = {
	delayEquipping = true,
}

NierEquip.toolTip = nil

NierEquip.unequipSwitch = {}

function NierEquip:OnEnable()
	if not self.db.char.originalEquipments then
		self.db.char.originalEquipments = {}
	end

	self.core.OnClick = function() NierEquip:ToggleGears() end

	self:RegisterEvent("PLAYER_AURAS_CHANGED", "CheckEquip")
	self:RegisterEvent("PLAYER_REGEN_ENABLED", "CheckEquip")
	self:RegisterEvent("PLAYER_CONTROL_GAINED", "CheckEquip")
	self:RegisterEvent("PLAYER_ALIVE", "CheckEquip")
	self:RegisterEvent("PLAYER_UNGHOST", "CheckEquip")

	self:RegisterEvent("UNIT_INVENTORY_CHANGED", "CheckInventory")

	self:RegisterEvent("UNIT_SPELLCAST_FAILED", "CheckEquip")
	self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", "CheckEquip")
	self:RegisterEvent("UNIT_SPELLCAST_STOP", "CheckEquip")

	self:CheckInventory("player")
	self:CheckEquip()
end

local toolTip = CreateFrame("GameTooltip", "NierEquipTooltip", nil, "GameTooltipTemplate")
function NierEquip:CheckEquip()
	if not self.core:IsActive() then return end
	local text 

	prevMountType = mountType
	mountType = MT_UNMOUNT

	local i, index, cancel = 1, GetPlayerBuff(1,"HELPFUL|CANCELABLE")
	while index > 0 do
		if (cancel == 1) then
			toolTip:SetOwner(WorldFrame,"ANCHOR_NONE")
			toolTip:SetPlayerBuff(index)

			-- Class specific equip check
			local _, class = UnitClass("player")
			if class == "SHAMAN" then
				-- Pass "Ghost Wolf"
				if NierEquipTooltipTextLeft1:GetText() == GetSpellInfo(2645) then break end
			elseif class == "DRUID" then
				if NierEquipTooltipTextLeft1:GetText() == GetSpellInfo(33943) or	-- Flight Form
					NierEquipTooltipTextLeft1:GetText() == GetSpellInfo(40120)		-- Swift Flight Form
				then
					self.core:Debug("Mounting Flightform")
					mountType = MT_FLIGHTFORM
					break
				end
			end

			text = NierEquipTooltipTextLeft2:GetText()
			if text then
				if string.match(text, PATTERN_VECHILE) then
					mountType = MT_VECHILE
					self.core:Debug("Mounting Flightform")
					break
				elseif string.match(text, PATTERN_AIRCRAFT) then
					mountType = MT_AIRCRAFT
					self.core:Debug("Mounting Aircraft")
					break
				end
			end

		end
		i = i + 1
		index, cancel = GetPlayerBuff(i,"HELPFUL|CANCELABLE")
	end

	if mountType == MT_UNMOUNT and self.unequipSwitch["toggleGears"] then
		self.unequipSwitch["toggleGears"] = nil
	end

	for k, v in pairs(self.unequipSwitch) do
		if v then
			mountType = MT_UNMOUNT
			break
		end
	end

	if mountType == MT_UNMOUNT then
		self:UnequipGears()
	elseif prevMountType == MT_UNMOUNT and mountType ~= MT_UNMOUNT then
		self:EquipGears()
	end
end

function NierEquip:EquipGears()
	if InCombatLockdown() then return end
	if UnitIsDeadOrGhost("player") then return end
	if not HasFullControl() then return end

	local gearSet
	if mountType == MT_UNMOUNT then 
		return
	elseif mountType == MT_VECHILE or mountType == MT_AIRCRAFT then
		gearSet = gears.normal
	elseif mountType == MT_FLIGHTFORM then
		gearSet = gears.druid
	end

	actualGears = {}
	local bag, slot
	for bag = 0, NUM_BAG_FRAMES do
		for slot = 1, GetContainerNumSlots(bag) do
			local itemLink = GetContainerItemLink(bag, slot)
			for k, v in pairs(gearSet) do
				if itemLink and string.match(itemLink, v.pattern) then
					local tempGear = {
						link = itemLink,
						slot = v.slot,
					}
					actualGears[k] = tempGear
				end
			end
		end
	end

	if actualGears.crop then
		local tempGear = actualGears.crop
		actualGears = {}
		actualGears.crop = tempGear
	end

	local text = ""

	for k, v in pairs(actualGears) do
		local tempLink = GetInventoryItemLink("player", v.slot )
		local backupLink = self.db.char.originalEquipments[v.slot]
		if tempLink and (not backupLink) then
				self.db.char.originalEquipments[v.slot] = tempLink
		end
		EquipItemByName(v.link, v.slot)
		equippedGears[v.slot] = v.link
		text = text .. v.link .. " "
	end

	if text ~= "" then
		self.core:Print(L["Equipping"].." - "..text)
	end
end

function NierEquip:UnequipGears()
	if InCombatLockdown() then return end
	if UnitIsDeadOrGhost("player") then return end
	if not HasFullControl() then return end
	local spell,_,_,_,stTime,edTime,isTradeSkill = UnitCastingInfo("player")
	--[[
	if spell then
		if isTradeSkill then return end
		if not attackingSpells[spell] then return end
	end
	]]

	local text = ""

	local hasPending = false

	for k, v in pairs(pendingEquipments) do
		local tempLink = GetInventoryItemLink("player", k )
		if tempLink and tempLink == v then
			pendingEquipments[k] = nil
		else
			equippedGears[k] = nil
			EquipItemByName(v, k)
			text = text .. v .. " "
			hasPending = true
		end
	end

	if not hasPending then 
		for k, v in pairs(self.db.char.originalEquipments) do
			pendingEquipments[k] = v
			equippedGears[k] = nil
			EquipItemByName(v, k)
			self.db.char.originalEquipments[k] = nil
			text = text .. v .. " "
		end
	end

	if text ~= "" then
		self.core:Print(L["Equipping"].." - "..text)
	end
end

function NierEquip:CheckInventory(unitId)

	if unitId ~= "player" then return end

	for k, v in pairs(pendingEquipments) do
		local tempLink = GetInventoryItemLink("player", k )
		if tempLink and tempLink == v then
			pendingEquipments[k] = nil
		end
	end

	local gearEquipped = false
	for k, v in pairs(equippedGears) do
		local itemLink = GetInventoryItemLink("player", k)
		gearEquipped = true
		if itemLink ~= v then
			gearEquipped = false
			break
		end
	end

	if gearEquipped then
		self.textDisplay = L["Equipped"]
		if self.core.iconFrame then
			self.core.iconFrame:SetTexture("Interface\\Icons\\Ability_Mount_NightmareHorse")
		end
		if self.core.minimapIcon then
			self.core.minimapIcon:SetTexture("Interface\\Icons\\Ability_Mount_NightmareHorse")
		end
		self.toolTip = {}
		table.insert(self.toolTip, {
			["text"] = L["Unequip gears"],
			["func"] = self.UnequipGears,
		})

		table.insert(self.toolTip, {
			["text"] = L["Pending gears"],
			["textR"] = 0.5,
			["textG"] = 0.5,
			["textB"] = 0.5,
		})

		for k, v in pairs(self.db.char.originalEquipments) do
			table.insert(self.toolTip, {
				["text"] = v,
			})
		end
	else
		self.textDisplay = L["Unequipped"]
		if self.core.iconFrame then
			self.core.iconFrame:SetTexture("Interface\\Icons\\Ability_Rogue_Sprint")
		end
		if self.core.minimapIcon then
			self.core.minimapIcon:SetTexture("Interface\\Icons\\Ability_Rogue_Sprint")
		end
		self.toolTip = {}
		table.insert(self.toolTip, {
			["text"] = L["Equip gears"],
			["func"] = self.CheckEquip,
		})
		mountType = MT_UNMOUNT
	end
	self.core:UpdateDisplay()
end

function NierEquip:ToggleGears()
	self.unequipSwitch["toggleGears"] = not self.unequipSwitch["toggleGears"]
	self:CheckEquip()
end
